package cn.lg.soar.system.biz.modules.auth.service.impl;

import cn.lg.soar.database.base.service.impl.BaseServiceImpl;
import cn.lg.soar.system.biz.config.SystemCacheKey;
import cn.lg.soar.system.biz.modules.auth.entity.Component;
import cn.lg.soar.system.biz.modules.auth.entity.Permit;
import cn.lg.soar.system.biz.modules.auth.mapper.ComponentMapper;
import cn.lg.soar.system.biz.modules.auth.model.ComponentBatchCreateVO;
import cn.lg.soar.system.biz.modules.auth.model.ComponentVO;
import cn.lg.soar.system.biz.modules.auth.service.ComponentService;
import cn.lg.soar.system.biz.modules.auth.service.IPermitService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 组件
 * @author luguoxiang
 * @since 2025-05-03
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
@Service
public class ComponentServiceImpl extends BaseServiceImpl<ComponentMapper, Component> implements ComponentService {

    @Autowired
    private IPermitService permitService;

    @Cacheable(value = SystemCacheKey.TREE, key = "'component'")
    public List<ComponentVO> tree() {
        List<Component> list = list();
        Map<Integer, List<Component>> group = list.stream().collect(Collectors.groupingBy(Component::getParentId));
        List<ComponentVO> vos = new ArrayList<>(128);
        for (Component component : list) {
            if (component.getParentId() == 0) {
                ComponentVO componentVO = new ComponentVO(component, group.get(component.getId()));
                vos.add(componentVO);
            }
        }
        return vos;
    }

    @Override
    public ComponentVO detail(Long id) {
        Component component = getById(id);
        List<Component> list = list(Wrappers.<Component>lambdaQuery().eq(Component::getParentId, id));
        return new ComponentVO(component, list);
    }

    @CacheEvict(value = SystemCacheKey.TREE, key = "'component'")
    @Override
    public boolean save(Component entity) {
        return super.save(entity);
    }

    @CacheEvict(value = SystemCacheKey.TREE, key = "'component'")
    @Override
    public boolean updateById(Component entity) {
        return super.updateById(entity);
    }

    @CacheEvict(value = SystemCacheKey.TREE, key = "'component'")
    @Override
    public boolean removeById(Component entity) {
        return super.removeById(entity);
    }

    @CacheEvict(value = SystemCacheKey.TREE, key = "'component'")
    @Override
    public boolean removeByIds(Collection<?> list, boolean useFill) {
        return super.removeByIds(list, useFill);
    }

    @CacheEvict(value = SystemCacheKey.TREE, key = "'component'")
    @Override
    public void batchCreate(List<ComponentBatchCreateVO> data) throws ExecutionException, InterruptedException {
        int size = data.size();
        // 查接口权限
        CompletableFuture<Map<String, Integer>> permitFuture = CompletableFuture.supplyAsync(() -> {
            permitService.scanServletPathGenPermit();
            List<Permit> permits = permitService.list(Wrappers.<Permit>lambdaQuery().select(Permit::getCode, Permit::getId));
            return permits.stream().collect(Collectors.toMap(Permit::getCode, Permit::getId));
        });
        // 查现有数据
        List<Component> list = list(
                Wrappers.<Component>lambdaQuery()
                        .select(
                                Component::getId,
                                Component::getCode,
                                Component::getParentId,
                                Component::getName,
                                Component::getPath,
                                Component::getPermitIds
                        )
        );
        Map<String, Component> map = list.stream().collect(Collectors.toMap(Component::getCode, x -> {
            x.setCode(null);
            return x;
        }));
        list.clear();
        // 判断是否需要更新
        BiFunction<Component, Component, Boolean> diff = (db, x) -> {
            if (!Objects.equals(db.getParentId(), x.getParentId())) {
                return true;
            }
            if (!Objects.equals(db.getPath(), x.getPath())) {
                return true;
            }
            if (!Objects.equals(db.getName(), x.getName())) {
                return true;
            }
            if (!Arrays.equals(db.getPermitIds(), x.getPermitIds())) {
                return true;
            }
            return false;
        };
        // 获取权限
        Map<String, Integer> permitMap = permitFuture.get();
        Function<List<String>, Integer[]> mapperPermit = permits -> permits.stream()
                .distinct()
                .map(permitMap::get)
                .filter(Objects::nonNull)
                .toArray(Integer[]::new);
        // 分组处理
        List<Component> insets = new ArrayList<>(size);
        List<Component> updates = new ArrayList<>(size);
        for (int i = 0; i < size; i++) {
            ComponentBatchCreateVO vo = data.get(i);
            String code = vo.getCode();
            Integer[] permitIds = mapperPermit.apply(vo.getPermits());
            Component component = map.get(code);
            if (component == null) {
                component = new Component();
                component.setCode(code);
                component.setParentId(0);
                component.setPath(vo.getPath());
                component.setName(vo.getName());
                component.setPermitIds(permitIds);
                insets.add(component);
                continue;
            }
            Component update = new Component();
            update.setId(component.getId());
            update.setParentId(0);
            update.setPath(vo.getPath());
            update.setName(vo.getName());
            update.setPermitIds(permitIds);
            if (diff.apply(component, update)) {
                updates.add(update);
            }
        }
        // 页面入库
        saveBatch(insets);
        updateBatchById(updates);
        // 查现有数据
        list = list(
                Wrappers.<Component>lambdaQuery()
                        .select(
                                Component::getId,
                                Component::getCode,
                                Component::getParentId,
                                Component::getName,
                                Component::getPath,
                                Component::getPermitIds
                        )
        );
        map = list.stream().collect(Collectors.toMap(Component::getCode, x -> {
            x.setCode(null);
            return x;
        }));
        list.clear();
        insets.clear();
        updates.clear();
        for (int i = 0; i < size; i++) {
            ComponentBatchCreateVO vo = data.get(i);
            String code = vo.getCode();
            Integer parentId = map.get(code).getId();
            ComponentBatchCreateVO.Element[] voElements = vo.getElements();
            for (int i1 = 0; i1 < voElements.length; i1++) {
                ComponentBatchCreateVO.Element voElement = voElements[i1];
                code = voElement.getCode();
                Component element = map.get(code);
                if (element == null) {
                    element = new Component();
                    element.setParentId(parentId);
                    element.setCode(code);
                    element.setPath("");
                    element.setName(voElement.getName());
                    element.setPermitIds(mapperPermit.apply(voElement.getPermits()));
                    insets.add(element);
                    continue;
                }
                Component update = new Component();
                update.setId(element.getId());
                update.setParentId(parentId);
                update.setPath("");
                update.setName(voElement.getName());
                update.setPermitIds(mapperPermit.apply(voElement.getPermits()));
                if (diff.apply(element, update)) {
                    updates.add(update);
                }
            }
        }
        // 页面按钮入库
        saveBatch(insets);
        updateBatchById(updates);
    }

    @Override
    public void clearCache() {

    }
}
